﻿#ifndef LK_SOUND_SOUDBUFFER_
#define LK_SOUND_SOUDBUFFER_
/**@author 由W意波(LuoJun)编写*/
namespace LK
{
	namespace Sound
	{
		/**@brief 缓存块,提供读和写的同步*/
		struct SoundBuffer :public LK::Collection::DefaultArray<u8>
		{
			/**@brief 线程同步控制*/
			Mutex tc;
			/**@brief 禁止复制构造*/
			SoundBuffer(const SoundBuffer&){}
			/**@brief 禁止赋值运算*/
			void operator=(const SoundBuffer&){}
		protected:
			/**@brief 最新的读取点位置（%Length就得到具体读取位置）*/
			long long readingPosition;
			/**@brief 最新的写入点位置（%Length就得到具体写入位置）*/
			long long writingPosition;
			/**@brief 向前读取空间（相对读取位置而言）*/
			index_t sizeBefore;
			/**@brief 预留的前读取空间，默认为创建Buffer使的大小的1/4*/
			index_t sizeBeforeMinimum;
			/**@brief 向后读取空间（相对读取位置而言）*/
			index_t sizeAfter;
			/**@brief 是否正在读取，需要同步，读过程要求暂停调整大小、回退操作*/
			bool isReading;
			/**@brief 是否正在写入，写入过程要求暂停调整大小、回退操作*/
			bool isWriting;
			/**@brief 读操作遇上无内容可读现象*/
			bool readNothing;
			/**@brief 写操作遇上无内容可写现象*/
			bool writeNothing;
			/**@brief 是否正在调整大小，调整大小过程要求暂停其他操作*/
			bool isResizing;
			/**@brief 是否正在回退，回退过程要求暂停读写操作*/
			bool isRollbacking;
			/**@brief 向后写入一段数据，若无法写完则一直等待，返回实际写入数量*/
			index_t PutAfter(u8 const*p,index_t len);
			/**@brief 向前写入一段数据，若无法写完则一直等待*/
			index_t PutBefore(u8 const*p, index_t len);
		public:
			/**@brief 默认缓冲大小*/
			static index_t DefaultSize;
			/**@brief 创建一个大小为len字节的缓存块*/
			SoundBuffer(index_t len = DefaultSize);
			/**@brief 虚析构函数*/
			virtual ~SoundBuffer();
			/**@brief 重置除缓存大小外的参数*/
			virtual void Reset();
			/**@brief 调整缓存块大小（字节）*/
			virtual index_t Resize(index_t len);
			/**@brief 设置预留的后退空间，不能超过总空间的一半，调整大小时将按照总空间二分之一予以限制*/
			void SetMinimumSizeBefore(size_t);
			/**@brief 获取可读取字节数*/
			index_t GetReadable()const;
			/**@brief 获取可写入字节数*/
			index_t GetWriteable()const;
			/**@brief 读位置回退,返回实际回退的字节数*/
			index_t Rollback(index_t);
			/**@brief 读位置前进,返回实际前进的字节数*/
			index_t Skip(index_t);
			/**@brief 向后读取一定字节数的内容，成功读取时，读取位置将随之后移，内容不足时将一直等待*/
			Collection::PArray<u8> GetAfter(index_t);
			/**@brief 向前读取一定字节数的内容，成功读取时，读取位置将随之前移，内容不足时将一直等待*/
			Collection::PArray<u8> GetBefore(index_t);
			/**@brief 向后写入一段数据，若无法写完则一直等待，返回实际写入数量*/
			template<typename T>index_t PutAfter(const Collection::PArray<T>&);
			/**@brief 向前写入一段数据，若无法写完则一直等待*/
			template<typename T>index_t PutBefore(const Collection::PArray<T>&);
		};
		/**@brief 向后写入一段数据，若无法写完则一直等待*/
		template<typename T> index_t SoundBuffer::PutAfter(const Collection::PArray<T>&xArray){return PutAfter((u8 const*)(const T*)xArray,xArray.GetLengthOfBytes());}
		/**@brief 向前写入一段数据，若无法写完则一直等待*/
		template<typename T>index_t SoundBuffer::PutBefore(const Collection::PArray<T>&xArray) { return PutBefore((u8 const*)(const T*)xArray, xArray.GetLengthOfBytes()); }
	}

}
#endif
